package com.hjt.gulimall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.hjt.common.to.ware.SkuInfoTo;
import com.hjt.gulimall.cart.feign.ProductFeignService;
import com.hjt.gulimall.cart.interceptor.CartInterceptor;
import com.hjt.gulimall.cart.service.CartService;
import com.hjt.gulimall.cart.vo.Cart;
import com.hjt.gulimall.cart.vo.CartItem;
import com.hjt.gulimall.cart.vo.UserLoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author:97007
 * @date:2021/10/1 9:46
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private ThreadPoolExecutor executor;


    private final String CART_PREFIX = "gulimall:cart:";

    @Override
    public CartItem addToCart(Long skuId, Integer count) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, String, String> ops  = getCartOps();
        String resultString = ops.get(skuId.toString());
        CartItem cartItem;
        // 1.购物车中已经有商品，添加数量即可
        if (StringUtils.hasLength(resultString)) {
            cartItem = JSON.parseObject(resultString, CartItem.class);
            cartItem.setCount(cartItem.getCount() + count);
        }
        // 2.购物车中没有该商品，去查询数据
        else {
            cartItem = new CartItem();
            CompletableFuture<Void> skuInfoFuture = CompletableFuture.runAsync(() -> {
                cartItem.setSkuId(skuId);
                // 1.远程查询要添加的商品的信息
                SkuInfoTo skuInfo = productFeignService.getSkuInfo(skuId);
                // 2.商品信息添加到购物车中
                cartItem.setImage(skuInfo.getSkuDefaultImg());
                cartItem.setChecked(true);
                cartItem.setTitle(skuInfo.getSkuTitle());
                cartItem.setPrice(skuInfo.getPrice());
                cartItem.setCount(count);
            }, executor);

            // 3.sku的销售属性组合信息
            CompletableFuture<Void> skuAttrFuture = CompletableFuture.runAsync(() -> {
                List<String> attrList = productFeignService.getSaleAttrAsStringListBySkuId(skuId);
                cartItem.setSkuAttr(attrList);
            }, executor);

            CompletableFuture.allOf(skuInfoFuture,skuAttrFuture).get();
        }

        // 3.保存到redis中
        ops.put(skuId.toString(), JSON.toJSONString(cartItem));

        return cartItem;
    }

    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, String, String> ops = getCartOps();
        String resultString = ops.get(skuId.toString());
        return JSON.parseObject(resultString,CartItem.class);
    }


    @Override
    public Cart getCart() throws ExecutionException, InterruptedException {
        UserLoginVo userLoginVo = CartInterceptor.threadLocal.get();
        Cart cart = new Cart();
        // 获取临时购物车的购物项
        List<CartItem> tempCartItems = getCartItems(userLoginVo.getUserKey());
        // 1.登录了
        if (userLoginVo.getUserId() != null) {
            // 1.1 合并临时购物车：如果临时购物车不为空，将临时购物车中的内容添加到登录购物车中
            if (tempCartItems != null) {
                // 1.1.1 将临时购物车的内容添加到登录购物车
                for (CartItem tempCartItem : tempCartItems) {
                    addToCart(tempCartItem.getSkuId(), tempCartItem.getCount());
                }
                // 1.1.2 清空临时购物车
                    clearCart(userLoginVo.getUserKey());
            }
            // 1.2 查询登录购物车（包含了临时购物车的内容）
            List<CartItem> cartItems = getCartItems(userLoginVo.getUserId().toString());
            cart.setItems(cartItems);
        }
        // 2.没有登录，查询临时购物车
        else {
            cart.setItems(tempCartItems);
        }
        return cart;
    }

    // 修改购物项选中状态
    @Override
    public void checked(Long skuId, Boolean checked) {
        CartItem cartItem = getCartItem(skuId);
        cartItem.setChecked(checked);
        BoundHashOperations<String, String, String> ops = getCartOps();
        ops.put(skuId.toString(), JSON.toJSONString(cartItem));
    }

    // 根据memberId获取购物项列表
    @Override
    public List<CartItem> getCartItemList() {

        UserLoginVo userLoginVo = CartInterceptor.threadLocal.get();
        if (userLoginVo == null) {
            return null;
        } else {
            Long userId = userLoginVo.getUserId();
            // 根据userId获取所有的选中的购物项
            List<CartItem> cartItems = getCartItems(String.valueOf(userId));
            if (!CollectionUtils.isEmpty(cartItems)) {
                return cartItems.stream().filter(CartItem::getChecked).peek(cartItem -> {
                    // 查询最新价格
                    Long skuId = cartItem.getSkuId();
                    cartItem.setPrice(productFeignService.getPrice(skuId));
                }).collect(Collectors.toList());
            }
            return null;
        }
    }

    // 获取到操作redis中购物车的方法（优先获取登录购物车）
    private BoundHashOperations<String, String, String> getCartOps() {
        // 根据用户类型生成用户购物车的key
        UserLoginVo userLoginVo = CartInterceptor.threadLocal.get();
        String cartKey = "";
        // 登录购物车
        if (userLoginVo.getUserId() != null) {
            Long userId = userLoginVo.getUserId();
            cartKey = CART_PREFIX + userId;
        } else {
            // 临时购物车
            cartKey = CART_PREFIX +  userLoginVo.getUserKey();
        }
        return redisTemplate.boundHashOps(cartKey);
    }

    // 根据传入的key获取所有的购物项
    private List<CartItem> getCartItems(String key) {

        BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps(CART_PREFIX +  key);
        // 2。查询所有购物项
        List<String> values = ops.values();
        if (!CollectionUtils.isEmpty(values)) {
            // string转换为CartItem,封装成列表
            return values.stream().map((resultString) -> JSON.parseObject(resultString, CartItem.class)).collect(Collectors.toList());
        }
        return null;
    }

    // 清空购物车
    private void clearCart(String key) {
        redisTemplate.delete(CART_PREFIX + key);
    }
}
